package org.example.utils.post.theme;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.example.dao.dao.post.PThemeDao;
import org.example.dao.entity.post.PTheme;
import org.example.exception.ServerErrorException;
import org.example.skytool.json.JackSonUtil;
import org.example.skytool.redis.CacheClient;
import org.example.skytool.redis.RedisUtils;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import static org.example.skytool.redis.RedisConstants.*;
/**
 * @author 22449
 */
@Component
public class RedisThemeService {

    @Resource
    private RedisUtils redisUtils;
    @Resource
    private PThemeDao pThemeDao;

    @Resource
    private CacheClient cacheClient;

    public String getThemeListHeader(){
        String header = POST_MOUDLE + POST_THEME_CONTROLLER + POST_THEME_LIST;
        return header;
    }

    public String getThemeListLockHeader(){
        String header = POST_MOUDLE + POST_THEME_CONTROLLER + POST_THEME_LOCK;
        return header;
    }

    public IPage<PTheme> getThemeList(Integer start,Integer limit){
        start--;
        // 定义参数和回退函数
        String cacheKey = getThemeListHeader();
        Map<String, Object> param = new HashMap<>();
        String lockKey = getThemeListLockHeader();
        Function<Map, Long> dbFallback = params -> {
            Long num = createThemeList();
            return num;
        };
        Long time = 30L;
        TimeUnit unit = TimeUnit.MINUTES;
        Long nullTtl = 30L;

        List<String> list = cacheClient.queryList(cacheKey,start,limit,param,
                lockKey,dbFallback,time,unit,nullTtl);

        if(list==null){
            throw new ServerErrorException("服务器构造theme失败");
        }

        List<PTheme> data = new ArrayList<>();
        for(String json : list){
            data.add(JackSonUtil.parse(PTheme.class,json));
        }

        IPage<PTheme> page = new Page<>();
        page.setRecords(data);
        page.setCurrent(start);
        page.setSize(limit);
        page.setTotal(redisUtils.listGetSize(getThemeListHeader()));
        page.setPages((long) Math.ceil(page.getTotal()/page.getSize()));

        return page;
    }

    private Long createThemeList(){
        Long start = 1L;
        Long limit = 20L;
        Long total = 0L;
        Long count = 0L;
        List<PTheme> list = null;
        IPage<PTheme> page = null;

        do{
            LambdaQueryWrapper<PTheme> lambdaQueryWrapper = new LambdaQueryWrapper<>();
            lambdaQueryWrapper.eq(PTheme::getIsValid,1);
            page = pThemeDao.selectPage(new Page<>(start,limit),lambdaQueryWrapper);

            if(total == 0){
                total = page.getTotal();
            }
            list = page.getRecords();

            if(list==null||list.size()==0){
                break;
            }

            List<String> data = new ArrayList<>();

            for(PTheme theme : page.getRecords()){
                data.add(JackSonUtil.encode(theme));
            }

            redisUtils.listRightAddAll(getThemeListHeader(),data.toArray(new String[0]));

            if(count.equals(total)){
                break;
            }

            start++;

            if(start*limit<total){
                count = start*limit;
            }else{
                count = total;
            }

        }while(count<=total);

        return total;
    }



}
